home *** CD-ROM | disk | FTP | other *** search
/ Java Developer's Companion / Java Developer's Companion.iso / binaries / Windows / jsdk / src / sun / servlet / apache / ServletGateConnection.java < prev   
Encoding:
Java Source  |  1997-07-18  |  24.5 KB  |  940 lines

  1. // @(#)ServletGateConnection.java    1.20 97/05/22
  2. //
  3. // ServletGateConnection - a program that runs Servlets
  4. //
  5. // Copyright (c) 1996 Sun Microsystems, Inc.  All Rights reserved
  6. // Permission to use, copy, modify, and distribute this software
  7. // and its documentation for NON-COMMERCIAL purposes and without
  8. // fee is hereby granted provided that this copyright notice
  9. // appears in all copies. Please refer to the file copyright.html
  10. // for further important copyright and licensing information.
  11. //
  12. // SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13. // THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14. // TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15. // PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16. // ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17. // DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  
  19. package sun.servlet.apache;
  20.  
  21. import java.io.*;
  22. import java.util.*;
  23. import javax.servlet.*;
  24. import javax.servlet.http.*;
  25. import java.util.StringTokenizer;
  26.  
  27. /** A program that runs Servlets.
  28. ** <P>
  29. ** This is a web program in java, but instead of actually serving
  30. ** content it instead turns the web requests into Jeeves-compatible
  31. ** Servlet requests, and then runs the Servlets.
  32. */
  33.  
  34. public abstract class ServletGateConnection
  35.     implements HttpServletRequest, HttpServletResponse {
  36.  
  37.     protected ServletGate serve;
  38.  
  39.     protected ServletInputStream in;
  40.     protected ServletOutputStream out;
  41.  
  42.     /** Constructor.
  43.     */
  44.     public ServletGateConnection(ServletGate serve, InputStream in,
  45.                  OutputStream out ) {
  46.     // Save arguments.
  47.     this.serve = serve;
  48.  
  49.     // Make the streams.
  50.     this.in = makeServletInputStream( in );
  51.     this.out = makeServletOutputStream( out );
  52.     
  53.     }
  54.  
  55.     protected ServletInputStream makeServletInputStream( InputStream in ) {
  56.     return new AServletInputStream( in );
  57.     }
  58.     
  59.     protected ServletOutputStream makeServletOutputStream( OutputStream out ) {
  60.     return new AServletOutputStream( out, this );
  61.     }
  62.  
  63.     private final String PREFIX = "/servlet/";
  64.  
  65.     protected void handle() {
  66.     String requestPath = getRequestPath();
  67.     String servletName = null;
  68.  
  69.     if (requestPath != null && requestPath.startsWith(PREFIX) 
  70.         && requestPath.length() > PREFIX.length()) {
  71.         
  72.         servletName = requestPath.substring(PREFIX.length());
  73.         // Strip off path info
  74.         if (servletName.indexOf("/") != -1) {
  75.         servletName = servletName.substring(0,servletName.indexOf("/"));
  76.         }
  77.  
  78.         Servlet servlet = findServlet( servletName );
  79.         if ( servlet != null )
  80.         runServlet( servlet );
  81.     }
  82.     }
  83.  
  84.     protected Servlet findServlet( String servletName ) {
  85.     // See if we have already instantiated this one.
  86.     Servlet servlet = (Servlet) serve.servlets.get( servletName );
  87.     if ( servlet != null )
  88.         return servlet;
  89.  
  90.     // Make a new one.
  91.     try {
  92.         String cname = 
  93.         serve.servletProperties.getProperty("servlet."+
  94.                             servletName+".code");
  95.         String initArgs = 
  96.         serve.servletProperties.getProperty("servlet."+
  97.                             servletName+".initArgs");
  98.         if (cname == null) cname = servletName;
  99.         servlet = (Servlet) Class.forName(cname).newInstance();
  100.         servlet.init(new ServletGateConfig((ServletContext)serve,
  101.                            servletName,initArgs));
  102.         serve.servlets.put( servletName, servlet );
  103.         return servlet;
  104.     }
  105.     catch ( ClassNotFoundException e ) {
  106.         problem("Class not found: " + servletName, 
  107.             SC_NOT_FOUND );
  108.     }
  109.     catch ( ClassCastException e ) {
  110.         problem("Class cast problem: " + e.getMessage(),
  111.             SC_INTERNAL_SERVER_ERROR );
  112.     }
  113.     catch ( InstantiationException e ) {
  114.         problem(
  115.         "Instantiation problem: " + e.getMessage(),
  116.         SC_INTERNAL_SERVER_ERROR );
  117.     }
  118.     catch ( IllegalAccessException e ) {
  119.         problem(
  120.         "Illegal class access: " + e.getMessage(),
  121.         SC_FORBIDDEN );
  122.     }
  123.     catch ( Exception e ) {
  124.         problem( e.toString(), SC_INTERNAL_SERVER_ERROR, e );
  125.     }
  126.  
  127.     // Failure.
  128.     return null;
  129.     }
  130.  
  131.     protected void runServlet( Servlet servlet ) {
  132.     // Set default response fields.
  133.     setStatus( SC_OK );
  134.     setHeader( "Server", serve.serverName() );
  135.     setDateHeader( "Date", System.currentTimeMillis() );
  136.     try {
  137.         servlet.service( this, this );
  138.     }
  139.     catch (Throwable t) {
  140.         problem( t.toString(), SC_INTERNAL_SERVER_ERROR, t );
  141.     }
  142.     }
  143.  
  144.     protected void problem( String logMessage, int resCode ) {
  145.     serve.log( logMessage );
  146.     try {
  147.         sendError( resCode );
  148.     }
  149.     catch (IOException ignore) { }
  150.     }
  151.  
  152.     protected void problem( String logMessage, int resCode, Throwable t )
  153.     {
  154.     serve.log( logMessage );
  155.     serve.log( t );
  156.     try {
  157.         sendError( resCode, t.toString() );
  158.     }
  159.     catch (IOException ignore) { }
  160.     }
  161.  
  162.     // Methods from HttpServletRequest.
  163.  
  164.     /** 
  165.      * Returns a particular variable for this request.
  166.      */
  167.     public abstract String getVar( String name );
  168.     public abstract Enumeration getVars();
  169.  
  170.     /**
  171.      * Returns the method with which the request was made. This can be "GET",
  172.      * "HEAD", "POST", or an extension method.
  173.      * Same as the CGI variable REQUEST_METHOD.
  174.      */
  175.     public String getMethod() {
  176.     return getVar( "REQUEST_METHOD" );
  177.     }
  178.  
  179.     /** 
  180.      * Returns the size of the request entity data, or -1 if not known.
  181.      * Same as the CGI variable CONTENT_LENGTH.
  182.      */
  183.     public int getContentLength() {
  184.     try {
  185.         return Integer.parseInt( getVar( "CONTENT_LENGTH" ) );
  186.     }
  187.     catch ( NumberFormatException e ) {
  188.         return -1;
  189.     }
  190.     }
  191.  
  192.     /** 
  193.      * Returns the MIME type of the request entity data, or null if
  194.      * not known.
  195.      * Same as the CGI variable CONTENT_TYPE.
  196.      */
  197.     public String getContentType() {
  198.     return getVar( "CONTENT_TYPE" );
  199.     }
  200.  
  201.     /** 
  202.      * Returns the full request URI.
  203.      */
  204.     public String getRequestURI() {
  205.     String queryPart = "";
  206.     String queryString = getQueryString();
  207.     if ( queryString != null && queryString.length() > 0 )
  208.         queryPart = "?" + queryString;
  209.     return getRequestPath() + queryPart;
  210.     }
  211.  
  212.     /** 
  213.      * Returns the part of the request URI that corresponds to the
  214.      *  servlet path plus the optional extra path information, if any
  215.      */
  216.     private String getRequestPath() {
  217.     String pi = getPathInfo();
  218.     if ( pi == null )
  219.         return getServletPath();
  220.     else
  221.         return getServletPath() + getPathInfo();
  222.     }
  223.  
  224.  
  225.    /**
  226.     * Returns the translated path for the specified virtual path.
  227.     */  
  228.    public String getRealPath(String path) {
  229.        return null;
  230.    }
  231.  
  232.  
  233.     /** 
  234.      * Returns the part of the request URI that referred to the servlet being
  235.      *  invoked.
  236.      *  Analogous to the CGI variable SCRIPT_NAME.
  237.      */
  238.     public String getServletPath() {
  239.     return getVar( "SCRIPT_NAME" );
  240.     }
  241.  
  242.     /** Returns optional extra path information following the servlet path, but
  243.      * immediately preceding the query string.  Returns null if not specified.
  244.      * Same as the CGI variable PATH_INFO.
  245.      */
  246.     public String getPathInfo() {
  247.     return getVar( "PATH_INFO" );
  248.     }
  249.  
  250.     /**
  251.      * Returns extra path information translated to a real path.  Returns
  252.      * null if no extra path information was specified.
  253.      * Same as the CGI variable PATH_TRANSLATED.
  254.      */
  255.     public String getPathTranslated() {
  256.     return getVar( "PATH_TRANSLATED" );
  257.     }
  258.  
  259.     /**
  260.      * Returns the query string part of the servlet URI, or null if not known.
  261.      * Same as the CGI variable QUERY_STRING.
  262.      */
  263.     public String getQueryString() {
  264.     return getVar( "QUERY_STRING" );
  265.     }
  266.  
  267.     private Dictionary params = null;
  268.  
  269.     /**
  270.      * Returns the value of the specified query string parameter, or null
  271.      * if not found.
  272.      * @param name the parameter name
  273.      */
  274.     public String getParameter( String name ) {
  275.  
  276.     if (params == null)
  277.         params = getParametersFromRequest();
  278.  
  279.     String vals[] = (String []) params.get(name);
  280.  
  281.     if (vals == null)
  282.         return null;
  283.  
  284.     String hackVal = vals[0];
  285.     for (int i = 1; i < vals.length; i++)
  286.         hackVal = hackVal + "," + vals[i];
  287.         
  288.     return hackVal;
  289.     }
  290.  
  291.     /**
  292.      * Returns an array of values for the specified query parameter.
  293.      */
  294.     public String [] getParameterValues(String name) {
  295.  
  296.     if (params == null)
  297.         params = getParametersFromRequest();
  298.  
  299.     return (String []) params.get(name); 
  300.     }
  301.  
  302.     /**
  303.      * Returns an enumeration of parameter names.
  304.      */
  305.     public Enumeration getParameterNames() {
  306.  
  307.     if (params == null)
  308.         params = getParametersFromRequest();
  309.  
  310.     return params.keys();
  311.  
  312.     }
  313.  
  314.     /** 
  315.      * Returns the protocol and version of the request as a string of
  316.      * the form <protocol>/<major version>.<minor version>.
  317.      * Same as the CGI variable SERVER_PROTOCOL.
  318.      */
  319.     public String getProtocol() {
  320.     return getVar( "SERVER_PROTOCOL" );
  321.     }
  322.  
  323.     /**
  324.      * Returns the scheme of the request -- always "http" for now.
  325.      */
  326.     public String getScheme() {
  327.     return "http";        // XXX might be "https" too!
  328.     }
  329.     
  330.     /**
  331.      * Returns the host name of the server as used in the <host> part of
  332.      * the request URI.
  333.      * Same as the CGI variable SERVER_NAME.
  334.      */
  335.     public String getServerName() {
  336.     return getVar( "SERVER_NAME" );
  337.     }
  338.  
  339.     /** 
  340.      * Returns the port number on which this request was received as used in
  341.      * the <port> part of the request URI.
  342.      * Same as the CGI variable SERVER_PORT.
  343.      */
  344.     public int getServerPort() {
  345.     try {
  346.         return Integer.parseInt( getVar( "SERVER_PORT" ) );
  347.     }
  348.     catch ( NumberFormatException e ) {
  349.         return 80;
  350.     }
  351.     }
  352.  
  353.     /**
  354.      * Returns the name of the user making this request, or null if not known.
  355.      * Same as the CGI variable REMOTE_USER.
  356.      */
  357.     public String getRemoteUser() {
  358.     return getVar( "REMOTE_USER" );
  359.     }
  360.  
  361.     /** 
  362.      * Returns the IP address of the agent that sent the request.
  363.      * Same as the CGI variable REMOTE_ADDR.
  364.      */
  365.     public String getRemoteAddr() {
  366.     return getVar( "REMOTE_ADDR" );
  367.     }
  368.  
  369.     /** 
  370.      * Returns the fully qualified host name of the agent that sent the
  371.      * request.
  372.      * Same as the CGI variable REMOTE_HOST.
  373.      */
  374.     public String getRemoteHost() {
  375.     return getVar( "REMOTE_HOST" );
  376.     }
  377.  
  378.     /** 
  379.      * Returns the authentication scheme of the request, or null if none.
  380.      * Same as the CGI variable AUTH_TYPE.
  381.      */
  382.     public String getAuthType() {
  383.     return getVar( "AUTH_TYPE" );
  384.     }
  385.  
  386.     /**
  387.      * Returns the value of a header field, or null if not known.
  388.      * Same as the information passed in the CGI variabled HTTP_*.
  389.      * @param name the header field name
  390.      */
  391.     public String getHeader( String name ) {
  392.     if (name == null) return null;
  393.     return getVar( "HTTP_" + name.replace('-','_').toUpperCase() );
  394.     }
  395.  
  396.     /**
  397.      * Returns the integer value of the specified header field.
  398.      * @param name the header field name
  399.      * @return the integer value of the header field, or -1 if the header
  400.      *         was not found
  401.      */
  402.     public int getIntHeader(String name) {
  403.         String val = getHeader(name);
  404.         if (val == null) return -1;
  405.         try {
  406.             return Integer.parseInt(val);
  407.         } catch (NumberFormatException e) {
  408.             return -1;
  409.         }
  410.     }
  411.  
  412.  
  413.     /**
  414.      * Returns the date value of the specified header field.
  415.      * @param name the header field name
  416.      * @return the date value of the header field in number of milliseconds
  417.      *         since the epoch, or -1 if the header was not found
  418.      */  
  419.     public long getDateHeader(String name) {
  420.         String val = getHeader(name);
  421.         if (val == null) return -1;
  422.     try {
  423.         return Date.parse( val );
  424.     } catch ( NumberFormatException e ) {
  425.         return -1;
  426.     }
  427.     }
  428.  
  429.     /*
  430.      * Possible request header field names.
  431.      */  
  432.     private static String[] HEADERS = {
  433.         /* Standard HTTP 1.0 and 1.1 headers */
  434.         "Accept",               "Accept-Charset",       "Accept-Encoding",
  435.         "Accept-Language",      "Accept-Ranges",        "Age",
  436.         "Allow",                "Authorization",        "Cache-Control",
  437.         "Connection",           "Content-Base",         "Content-Encoding",
  438.         "Content-Language",     "Content-Length",       "Content-Location",
  439.         "Content-MD5",          "Content-Range",        "Content-Type",
  440.         "Date",                 "ETag",                 "Expires",
  441.         "From",                 "Host",                 "If-Modified-Since",
  442.         "If-Match",             "If-None-Match",        "If-Range",
  443.         "If-Unmodified-Since",  "Last-Modified",        "Location",
  444.         "Max-Forwards",         "Pragma",               "Proxy-Authenticate",
  445.         "Proxy-Authorization",  "Public",               "Range",
  446.         "Referer",              "Retry-After",          "Server",
  447.         "Transfer-Encoding",    "Upgrade",              "User-Agent",
  448.         "Vary",                 "Via",                  "Warning",
  449.         "WWW-Authenticate",
  450.         /* Popular extension headers */
  451.         "Alternates",           "Content-Version",      "Cookie",
  452.         "Derived-From",         "Keep-Alive",           "Link",
  453.         "MIME-Version",         "URI",                  "Title"
  454.     };
  455.  
  456.  
  457.     /**
  458.      * Returns an Enumeration of the header names.
  459.      */
  460.     public Enumeration getHeaderNames() {
  461.     Vector heads = new Vector();
  462.     Enumeration enum = getVars();
  463.     while (enum.hasMoreElements()) {
  464.         String ohead = (String) enum.nextElement();
  465.         if (ohead == null || ohead.length() < 5) continue;
  466.         if (ohead.startsWith("HTTP_")) {
  467.                 String head = ohead.substring(5).toLowerCase().replace('_','-');
  468.                 for (int i = 0; i < HEADERS.length; i++) {
  469.                     if (head.equals(HEADERS[i].toLowerCase())) {
  470.                 heads.addElement(HEADERS[i]);
  471.             break;
  472.                     }
  473.                 }
  474.         }
  475.     }
  476.     return heads.elements();
  477.     }
  478.  
  479.     /** 
  480.      * Returns an input stream for reading request data.
  481.      */
  482.     public ServletInputStream getInputStream(){
  483.     return in;
  484.     }
  485.  
  486.     /** 
  487.      * Returns an server specific attribute.
  488.      */
  489.     public Object getAttribute(String name) {
  490.     return null;
  491.     }
  492.  
  493.     private Hashtable nullHashtable = new Hashtable();
  494.  
  495.     private Hashtable getParametersFromRequest() {
  496.  
  497.     Hashtable h = null;
  498.  
  499.     if (getMethod().equals("GET")) {
  500.         String s = getQueryString().toString();
  501.         if (s != null) {
  502.         try {
  503.             h = HttpUtils.parseQueryString(s);
  504.         } catch (IllegalArgumentException e) {
  505.             h = null;
  506.         }
  507.         }
  508.     } else if (getMethod().equals("POST")) {
  509.         if (getContentType().equals("application/x-www-form-urlencoded")) {
  510.         try {
  511.             h = HttpUtils.parsePostData(getContentLength(),
  512.                              getInputStream());
  513.         } catch (Exception e) {
  514.             h = null;
  515.         }
  516.         } 
  517.     }
  518.  
  519.     if (h == null)
  520.         h = nullHashtable;
  521.  
  522.     return h;
  523.     }
  524.  
  525.     // Methods from HttpServletResponse.
  526.  
  527.     private int resCode = -1;
  528.     private String resMessage = null;
  529.     private Vector resHeaderNames = new Vector();
  530.     private Vector resHeaderValues = new Vector();
  531.  
  532.     /** Sets the status code and message for this response.
  533.     ** @param resCode the status code
  534.     ** @param resMessage the status message
  535.     */
  536.     public void setStatus( int resCode, String resMessage )
  537.     {
  538.     this.resCode = resCode;
  539.     this.resMessage = resMessage;
  540.     }
  541.  
  542.     /** Sets the status code and a default message for this response.
  543.     ** @param resCode the status code
  544.     */
  545.     public void setStatus( int resCode )
  546.     {
  547.     switch ( resCode )
  548.         {
  549.         case SC_OK: setStatus( resCode, "Ok" ); break;
  550.         case SC_CREATED: setStatus( resCode, "Created" ); break;
  551.         case SC_ACCEPTED: setStatus( resCode, "Accepted" ); break;
  552.         case SC_NO_CONTENT: setStatus( resCode, "No content" ); break;
  553.         case SC_MOVED_PERMANENTLY:
  554.         setStatus( resCode, "Moved permanentently" ); break;
  555.         case SC_MOVED_TEMPORARILY:
  556.         setStatus( resCode, "Moved temporarily" ); break;
  557.         case SC_NOT_MODIFIED: setStatus( resCode, "Not modified" ); break;
  558.         case SC_BAD_REQUEST: setStatus( resCode, "Bad request" ); break;
  559.         case SC_UNAUTHORIZED: setStatus( resCode, "Unauthorized" ); break;
  560.         case SC_FORBIDDEN: setStatus( resCode, "Forbidden" ); break;
  561.         case SC_NOT_FOUND: setStatus( resCode, "Not found" ); break;
  562.         case SC_INTERNAL_SERVER_ERROR:
  563.         setStatus( resCode, "Internal server error" ); break;
  564.         case SC_NOT_IMPLEMENTED:
  565.         setStatus( resCode, "Not implemented" ); break;
  566.         case SC_SERVICE_UNAVAILABLE:
  567.         setStatus( resCode, "Service unavailable" ); break;
  568.         case SC_BAD_GATEWAY: setStatus( resCode, "Bad gateway" ); break;
  569.         default: setStatus( resCode, "" ); break;
  570.         }
  571.     }
  572.  
  573.     /** Sets the content length for this response.
  574.     ** @param length the content length
  575.     */
  576.     public void setContentLength( int length )
  577.     {
  578.     setIntHeader( "Content-length", length );
  579.     }
  580.  
  581.     /** Sets the content type for this response.
  582.     ** @param type the content type
  583.     */
  584.     public void setContentType( String type )
  585.     {
  586.     setHeader( "Content-type", type );
  587.     }
  588.  
  589.     /** Sets the value of a header field.
  590.     ** @param name the header field name
  591.     ** @param value the header field value
  592.     */
  593.     public void setHeader( String name, String value )
  594.     {
  595.     resHeaderNames.addElement( name );
  596.     resHeaderValues.addElement( value );
  597.     }
  598.     
  599.     /**
  600.      * Returns true iff the named header has been set.
  601.      * @param name the header field name
  602.      */
  603.     public boolean containsHeader (String name)
  604.     {
  605.     return resHeaderNames.contains (name);
  606.     }
  607.  
  608.     /** Sets the value of an integer header field.
  609.     ** @param name the header field name
  610.     ** @param value the header field integer value
  611.     */
  612.     public void setIntHeader( String name, int value )
  613.     {
  614.     setHeader( name, Integer.toString( value ) );
  615.     }
  616.  
  617.     /** Sets the value of a date header field.
  618.     ** @param name the header field name
  619.     ** @param value the header field date value
  620.     */
  621.     public void setDateHeader( String name, long value )
  622.     {
  623.     setHeader( name, to1123String( new Date( value ) ) );
  624.     }
  625.     
  626.     /// Converts a Date into an RFC-1123 string.
  627.     private static String to1123String( Date date )
  628.     {
  629.     String ds = date.toString();
  630.     int blank = ds.indexOf( ' ' );
  631.     return
  632.         ds.substring( 0, blank ) +
  633.         ( date.getDate() < 10 ? ", 0" : ", " ) +
  634.         date.toGMTString();
  635.     }
  636.  
  637.     /** Returns an output stream for writing response data.
  638.     */
  639.     public ServletOutputStream getOutputStream()
  640.     {
  641.     return out;
  642.     }
  643.  
  644.     private boolean headersWritten = false;
  645.  
  646.     /** Writes the status line and message headers for this response to the
  647.     ** output stream.
  648.     ** @exception IOException if an I/O error has occurred
  649.     */
  650.     void writeHeaders() throws IOException
  651.     {
  652.     if ( headersWritten )
  653.         return;
  654.     headersWritten = true;
  655.     if ( getProtocol().startsWith( "HTTP/1" ) )
  656.         {
  657.         out.println( getProtocol() + " " + resCode + " " + resMessage );
  658.         for ( int i = 0; i < resHeaderNames.size(); ++i )
  659.         {
  660.         String name = (String) resHeaderNames.elementAt( i );
  661.         String value = (String) resHeaderValues.elementAt( i );
  662.         if ( value != null )    // just in case
  663.             out.println( name + ": " + value );
  664.         }
  665.         out.println( "" );
  666.         out.flush();
  667.         }
  668.     }
  669.  
  670.     /** Writes an error response using the specified status code and message.
  671.     ** @param resCode the status code
  672.     ** @param resMessage the status message
  673.     ** @exception IOException if an I/O error has occurred
  674.     */
  675.     public void sendError( int resCode, String resMessage ) throws IOException
  676.     {
  677.     setStatus( resCode, resMessage );
  678.     realSendError();
  679.     }
  680.  
  681.     /** Writes an error response using the specified status code and a default
  682.     ** message.
  683.     ** @param resCode the status code
  684.     ** @exception IOException if an I/O error has occurred
  685.     */
  686.     public void sendError( int resCode ) throws IOException
  687.     {
  688.     setStatus( resCode );
  689.     realSendError();
  690.     }
  691.  
  692.     private void realSendError() throws IOException
  693.     {
  694.     setContentType( "text/html" );
  695.     out.println( "<HTML><HEAD>" );
  696.     out.println( "<TITLE>" + resCode + " " + resMessage + "</TITLE>" );
  697.     out.println( "</HEAD><BODY BGCOLOR=\"#a0c0a0\">" );
  698.     out.println( "<H2>" + resCode + " " + resMessage + "</H2>" );
  699.     out.println( "<HR>" );
  700.     serve.writeAddress( out );
  701.     out.println( "</BODY></HTML>" );
  702.     out.flush();
  703.     }
  704.  
  705.     private void realSendError( Throwable t ) throws IOException
  706.     {
  707.     setContentType( "text/html" );
  708.     writeHeaders();
  709.     out.println( "<HTML><HEAD>" );
  710.     out.println( "<TITLE>" + resCode + " " + resMessage + "</TITLE>" );
  711.     out.println( "</HEAD><BODY BGCOLOR=\"#a0c0a0\">" );
  712.     out.println( "<H2>" + resCode + " " + resMessage + "</H2>" );
  713.     out.println( "<PRE><CODE>" );
  714.     PrintStream p = new PrintStream( out );
  715.     t.printStackTrace( p );
  716.     p.flush();
  717.     out.println( "</CODE></PRE>" );
  718.     out.println( "<HR>" );
  719.     serve.writeAddress( out );
  720.     out.println( "</BODY></HTML>" );
  721.     out.flush();
  722.     }
  723.  
  724.     /** Sends a redirect message to the client using the specified redirect
  725.     ** location URL.
  726.     ** @param location the redirect location URL
  727.     ** @exception IOException if an I/O error has occurred
  728.     */
  729.     public void sendRedirect( String location ) 
  730.     throws IOException {
  731.  
  732.     setHeader( "Location", location );
  733.     sendError( SC_MOVED_TEMPORARILY );
  734.     }
  735.  
  736. }
  737.  
  738.  
  739. class ServletGateConfig implements ServletConfig {
  740.  
  741.     private Properties servletProperties = new Properties();
  742.     private ServletContext context;
  743.     private String servletName;
  744.  
  745.     public ServletGateConfig(ServletContext context, String servletName, 
  746.                  String propString) {
  747.  
  748.     this.context = context;
  749.  
  750.     if (propString != null) {
  751.         propString = propString.replace(',','\n');
  752.         StringBufferInputStream sbin = 
  753.         new StringBufferInputStream(propString);
  754.         String line;
  755.         DataInputStream ds = new DataInputStream(sbin);
  756.         try {
  757.         while ((line = ds.readLine()) != null) {
  758.             int equalTo = line.indexOf("=");
  759.             if (equalTo == -1)
  760.             continue;
  761.             String l = line.substring(0, equalTo);
  762.             String r = line.substring(equalTo + 1, line.length());
  763.             if (l != null && r != null)
  764.             servletProperties.put(l,r);
  765.         }
  766.         } catch (IOException e) {
  767.         System.err.println("Cannot read initial arguments for servlet "
  768.                    + servletName + ": ");
  769.         e.printStackTrace(System.err);
  770.         }
  771.     }
  772.     }
  773.  
  774.     // Methods from ServletConfig.
  775.  
  776.     /**
  777.      * Returns the context for the servlet.
  778.      */
  779.     public ServletContext getServletContext() {
  780.     return context;
  781.     }
  782.  
  783.     /** 
  784.      * Gets an initialization parameter of the servlet.
  785.      */
  786.     public String getInitParameter( String name ) {
  787.     // Default doesn't support servlet init params.
  788.     return (String) servletProperties.get(name);
  789.     }
  790.  
  791.     /** 
  792.      * Gets a enumeration of the initialization parameters of the servlet.
  793.      */
  794.     public Enumeration getInitParameterNames() {
  795.     // Default doesn't support servlet init params.
  796.     return servletProperties.propertyNames();
  797.     }
  798. }
  799.  
  800.  
  801. /** Minimal implementation of ServletInputStream.
  802. */
  803.  
  804. class AServletInputStream extends ServletInputStream
  805.     {
  806.  
  807.     protected InputStream in;
  808.  
  809.     public AServletInputStream( InputStream in )
  810.     {
  811.     this.in = in;
  812.     }
  813.  
  814.     public int readLine( byte[] b, int off, int len ) throws IOException
  815.     {
  816.     int off2 = off;
  817.     for ( off2 = off; off2 - off < len; ++off2 )
  818.         {
  819.         int r = read();
  820.         if ( r == -1 )
  821.         {
  822.         if ( off2 == off )
  823.             return -1;
  824.         break;
  825.         }
  826.         b[off2] = (byte) r;
  827.         }
  828.     return off2 - off;
  829.     }
  830.  
  831.     public int read() throws IOException
  832.     {
  833.     return in.read();
  834.     }
  835.  
  836.     public int read( byte[] b, int off, int len ) throws IOException
  837.     {
  838.     return in.read( b, off, len );
  839.     }
  840.  
  841.     public int available() throws IOException
  842.     {
  843.     return in.available();
  844.     }
  845.  
  846.     public void close() throws IOException
  847.     {
  848.     in.close();
  849.     }
  850.  
  851.     }
  852.  
  853.  
  854. /** Minimal implementation of ServletOutputStream.
  855. */
  856.  
  857. class AServletOutputStream extends ServletOutputStream
  858.     {
  859.  
  860.     protected PrintStream out;
  861.     protected ServletGateConnection conn;
  862.  
  863.     public AServletOutputStream( OutputStream out, ServletGateConnection conn )
  864.     {
  865.     this.out = new PrintStream( out );
  866.     this.conn = conn;
  867.     }
  868.  
  869.     public void write( int b ) throws IOException
  870.     {
  871.     conn.writeHeaders();
  872.     out.write( b );
  873.     }
  874.  
  875.     public void write( byte[] b, int off, int len ) throws IOException
  876.     {
  877.     conn.writeHeaders();
  878.     out.write( b, off, len );
  879.     }
  880.  
  881.     public void flush() throws IOException
  882.     {
  883.     conn.writeHeaders();
  884.     out.flush();
  885.     }
  886.  
  887.     public void close() throws IOException
  888.     {
  889.     conn.writeHeaders();
  890.     out.close();
  891.     }
  892.  
  893.     public void print( String s ) throws IOException
  894.     {
  895.     conn.writeHeaders();
  896.     out.print( s );
  897.     }
  898.  
  899.     public void print( int i ) throws IOException
  900.     {
  901.     conn.writeHeaders();
  902.         out.print( i );
  903.     }
  904.  
  905.     public void print( long l ) throws IOException
  906.     {
  907.     conn.writeHeaders();
  908.     out.print( l );
  909.     }
  910.  
  911.     public void println( String s ) throws IOException
  912.     {
  913.     conn.writeHeaders();
  914.     out.print( s );
  915.     println();
  916.     }
  917.  
  918.     public void println( int i ) throws IOException
  919.     {
  920.     conn.writeHeaders();
  921.     out.print( i );
  922.     println();
  923.     }
  924.  
  925.     public void println( long l ) throws IOException
  926.     {
  927.     conn.writeHeaders();
  928.     out.print( l );
  929.     println();
  930.     }
  931.  
  932.     public void println() throws IOException
  933.         {
  934.     conn.writeHeaders();
  935.     out.print("\r\n");
  936.     out.flush();
  937.     }
  938.  
  939.     }
  940.